﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Inscriptionem.Areas.Inscriptionem.Models.Enums;
using Inscriptionem.Areas.Inscriptionem.Models.Requests;
using Inscriptionem.Areas.Inscriptionem.Models.Views;
using Inscriptionem.Authorization;
using Inscriptionem.Controllers;
using Inscriptionem.Extensions;

namespace Inscriptionem.Areas.Inscriptionem.Controllers
{
    [InscriptionemAuthorize(MemberRole.Admin)]
    public class TagController : Controller
    {
        private readonly ORM.DB DB;
        public TagController()
        {
            DB = new ORM.DB();
        }

        public ActionResult Index()
        {
            return View("Index", new TagCollectionViewModel());
        }

        public ActionResult Add()
        {
            return View("Add", new TagViewModel());
        }

        [HttpPost]
        public ActionResult Add(TagRequestModel model)
        {
            var result = new TagViewModel();
            model.CopyTo(result);

            result.Error = ValidateTagAddModel(result);

            if (result.Error == TagError.None)
            {
                try
                {
                    var tag = new ORM.Tag()
                                  {
                                      Name = result.Name,
                                      Language = DB.Languages.First(l => l.ID == result.Language)
                                  };

                    DB.AddToTags(tag);
                    DB.SaveChanges();
                }
                catch (Exception)
                {
                    result.Error = TagError.Other;
                }
            }

            return View("Add", result);
        }

        [HttpPost]
        public ActionResult Edit(TagRequestModel model)
        {
            var result = new TagViewModel();
            model.CopyTo(result);

            // Not the best way to check if "Edit" button was pressed
            if (result.ID > 0 && string.IsNullOrWhiteSpace(result.Name))
            {
                var tag = DB.Tags.FirstOrDefault(t => t.ID == result.ID);
                if (tag == null)
                {
                    // Tag not found
                    return RedirectToAction("Index");
                }

                result.Name = tag.Name;
                result.Language = tag.Language.ID;

                // Roles will be automatically populated on View

                return View("Edit", result);
            }

            // Validate
            result.Error = ValidateTagEditModel(result);
            if (result.Error == TagError.None)
            {
                // Save changes
                try
                {
                    var tag = DB.Tags.FirstOrDefault(t => t.ID == result.ID);

                    if (tag == null)
                    {
                        return RedirectToAction("Index");
                    }

                    tag.Name = result.Name;

                    DB.SaveChanges();

                    return RedirectToAction("Index");
                }
                catch (Exception)
                {
                    result.Error = TagError.Other;
                }
            }

            return View("Edit", result);
        }

        [HttpPost]
        public ActionResult Delete(int ID)
        {
            if (ID <= 0)
            {
                return RedirectToAction("Index");
            }

            var tag = DB.Tags.FirstOrDefault(t => t.ID == ID);
            if (tag == null)
            {
                return RedirectToAction("Index");
            }

            TagError result = TagError.None;

            try
            {
                // Tag references
                var postTags = DB.PostTags.Where(pt => pt.Tag.ID == tag.ID);
                foreach (var postTag in postTags)
                {
                    DB.PostTags.DeleteObject(postTag);
                }

                var pageTags = DB.PageTags.Where(pt => pt.Tag.ID == tag.ID);
                foreach (var pageTag in pageTags)
                {
                    DB.PageTags.DeleteObject(pageTag);
                }

                // Tag
                DB.Tags.DeleteObject(tag);
                DB.SaveChanges();

                return RedirectToAction("Index");
            }
            catch (Exception)
            {
                result = TagError.Other;
            }

            return View("Delete", result);
        }

        [HttpPost]
        public ActionResult Search(string Text, int Page)
        {
            if (Page < 0)
            {
                Page = 0;
            }

            var result = new TagSearchCollectionViewModel { Page = Page, Text = Text };

            return View("Search", result);
        }

        public ActionResult Page(int ID)
        {
            if (ID <= 0)
            {
                return RedirectToAction("Index");
            }

            return View("Index", new PageCollectionViewModel() { Page = ID });
        }

        #region Pagination
        public ActionResult Pagination(global::Inscriptionem.Models.Menu.Requests.PaginationRequestModel model)
        {
            return new MenuController().Pagination(model);
        }
        #endregion

        #region Implementation
        private TagError ValidateTagAddModel(TagViewModel Model)
        {
            var editValidateResult = ValidateTagEditModel(Model);
            if (editValidateResult != TagError.None)
            {
                return editValidateResult;
            }

            var tag = DB.Tags.FirstOrDefault(t => t.Name.ToLower() == Model.Name.ToLower().Trim() && t.Language.ID == Model.Language);
            if (tag != null)
            {
                return TagError.TagAlreadyExists;
            }

            return TagError.None;
        }

        private TagError ValidateTagEditModel(TagViewModel Model)
        {
            if (string.IsNullOrWhiteSpace(Model.Name))
            {
                return TagError.TagEmpty;
            }

            var language = DB.Languages.FirstOrDefault(l => l.ID == Model.Language);
            if (language == null)
            {
                return TagError.TagLanguageEmpty;
            }

            return TagError.None;
        }
        #endregion
    }
}
